from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select

from app.db.postgres import get_session
from app.models import UserAccount, Role, Menu, RoleMenu, UserRole
from app.schemas.auth import LoginRequest, TokenResponse, ChangePasswordRequest
from app.schemas.user import UserRead
from app.core.security import verify_password, create_access_token, get_current_user, get_password_hash


router = APIRouter(prefix="/auth", tags=["auth"])


@router.post("/login", response_model=TokenResponse)
async def login(payload: LoginRequest, session: AsyncSession = Depends(get_session)):
    result = await session.execute(select(UserAccount).where(UserAccount.username == payload.username))
    user = result.scalar_one_or_none()
    if user is None or not user.enabled:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="用户名或密码错误")
    if not verify_password(payload.password, user.password_hash):
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="用户名或密码错误")
    token = create_access_token(str(user.id))
    return TokenResponse(access_token=token)


@router.get("/me", response_model=UserRead)
async def me(current_user: UserAccount = Depends(get_current_user)):
    return UserRead(
        id=current_user.id,
        username=current_user.username,
        full_name=current_user.full_name,
        email=current_user.email,
        enabled=current_user.enabled,
    )


@router.post("/change-password")
async def change_password(
    payload: ChangePasswordRequest,
    session: AsyncSession = Depends(get_session),
    current_user: UserAccount = Depends(get_current_user),
):
    # 验证原密码
    if not verify_password(payload.old_password, current_user.password_hash):
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="原密码不正确")
    # 更新新密码
    current_user.password_hash = get_password_hash(payload.new_password)
    await session.flush()
    await session.refresh(current_user)
    await session.commit()
    return {"ok": True}


@router.post("/bootstrap", response_model=UserRead)
async def bootstrap_admin(payload: LoginRequest, session: AsyncSession = Depends(get_session)):
    # 若系统内不存在任何用户，则允许创建第一个管理员用户
    count_result = await session.execute(select(UserAccount))
    if count_result.scalars().first() is not None:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="系统已初始化，禁止引导创建")
    user = UserAccount(
        username=payload.username,
        password_hash=get_password_hash(payload.password)
    )
    user.enabled = True
    session.add(user)
    await session.flush()
    await session.refresh(user)
    
    # 确保存在admin角色
    role_q = await session.execute(select(Role).where(Role.code == 'admin'))
    role = role_q.scalar_one_or_none()
    if role is None:
        role = Role(code='admin', name='超级管理员', description='系统默认超级管理员角色', enabled=True)
        session.add(role)
        await session.flush()
        await session.refresh(role)

    # 确保基础菜单存在（按path幂等创建）
    async def ensure_menu(path: str, name: str, parent_id=None, order_index: int = 0):
        m_q = await session.execute(select(Menu).where(Menu.path == path))
        m = m_q.scalar_one_or_none()
        if m is None:
            m = Menu(parent_id=parent_id, name=name, path=path, icon=None, order_index=order_index, enabled=True)
            session.add(m)
            await session.flush()
            await session.refresh(m)
        return m

    home = await ensure_menu('/home', '首页', None, 0)
    dashboard = await ensure_menu('/dashboard', '概览', None, 1)
    activities = await ensure_menu('/activities', '活动', None, 2)
    events = await ensure_menu('/events', '事件', None, 3)
    evaluations = await ensure_menu('/evaluations', '评分', None, 4)
    reports = await ensure_menu('/reports', '报告', None, 5)
    admin_root = await ensure_menu('/admin', '系统管理', None, 100)
    await ensure_menu('/admin/users', '用户管理', admin_root.id, 101)
    await ensure_menu('/admin/roles', '角色管理', admin_root.id, 102)
    await ensure_menu('/admin/menus', '菜单管理', admin_root.id, 103)

    # 将admin角色授权所有启用菜单（避免重复）
    enabled_menu_ids_res = await session.execute(select(Menu.id).where(Menu.enabled == True))
    enabled_menu_ids = set(enabled_menu_ids_res.scalars().all())
    existing_role_menu_res = await session.execute(select(RoleMenu.menu_id).where(RoleMenu.role_id == role.id))
    existing_menu_ids = set(existing_role_menu_res.scalars().all())
    need_assign_ids = enabled_menu_ids - existing_menu_ids
    for mid in need_assign_ids:
        session.add(RoleMenu(role_id=role.id, menu_id=mid))

    # 将新建用户赋予admin角色（避免重复）
    ur_exist = await session.execute(
        select(UserRole).where(UserRole.user_id == user.id, UserRole.role_id == role.id)
    )
    if ur_exist.scalar_one_or_none() is None:
        session.add(UserRole(user_id=user.id, role_id=role.id))

    await session.flush()
    await session.commit()
    return UserRead(id=user.id, username=user.username, full_name=None, email=None, enabled=user.enabled)